package com.mcptt.config.group;

import android.os.Handler;
import android.os.Message;

import com.cloudptt.api.comm.CheckData;
import com.cloudptt.api.product.log.Log;
import com.mcptt.comm.CommonFunc;
import com.mcptt.config.IDbOperation;
import com.mcptt.config.ISvrOperation;
import com.mcptt.config.callback.IParserCallback;
import com.mcptt.config.group.sub.DisplayName;
import com.mcptt.config.group.sub.ListEntry;
import com.mcptt.config.group.sub.PreferredVoiceEncodings;
import com.mcptt.config.group.sub.Ruleset;
import com.mcptt.config.group.sub.SupportedServices;
import com.mcptt.config.group.sub.sub.Entry;
import com.mcptt.db.DBAdapter;
import com.mcptt.db.model.AddrInfo;
import com.mcptt.db.model.ConfigFileInfo;
import com.mcptt.db.model.GroupMembInfo;
import com.mcptt.db.model.UserInfo;
import com.mcptt.http.operator.HttpOperator;
import com.mcptt.notify.xcap.XcapDoc;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import okhttp3.Response;

public class Group  implements IDbOperation,ISvrOperation
{
	private final static int OP_SUC = 0;
	private final static int OP_FAILED = 1;

	public static final String FileName_Mcptt = "org.3gpp.mcptt.mcptt-group";
	public static final String FileName_Mcvideo = "org.3gpp.mcptt.mcvideo-group";
	public static final String FileName_Mcdata = "org.3gpp.mcptt.mcdata-group";
	private static final String FilePath = "//config//group//";
	public static final String Name = "group";
	private static final String Namespace_Mcpttgi = "mcpttgi";
	public static final String Name_Sub = "list-service";
	// private static final String Name_SchemaLocation = "schemaLocation";
	// private static final String Name_Xsi = "xmlns:xsi";
	// private static final String Name_Xmlns = "xmlns";
	private static final String Name_Uri = "uri";

	// private String schemaLocation = null;
	// private String xsi = null;
	// private String xmlns = null;
	private String uri = null;
	private DisplayName displayName = null;
	private ListEntry listEntry = null;
	private PreferredVoiceEncodings preferredVoiceEncodings = null;
	private Ruleset ruleset = null;
	private SupportedServices supportedServices = null;
	private Map<String, String> ruleMap = null;

	private ConfigFileInfo info = null;

	private int mcType = UserInfo.McType_Ptt;
	private DBAdapter dbOperator = null;
	private String groupName = null;
	private IParserCallback callback = null;

	public Group(int mcType, DBAdapter dbOperator, String groupName, IParserCallback parserCallback)
	{
		this.mcType = mcType;
		this.dbOperator = dbOperator;
		this.groupName = groupName;
		this.info = readFromDb(groupName);
		parse(info);
	}

	private void parse(ConfigFileInfo info)
	{
		if(info == null)
		{
			return;
		}
		SAXBuilder builder = new SAXBuilder();// 实锟斤拷JDOM锟斤拷锟斤拷锟斤拷
		//	File file = new File(Environment.getExternalStorageDirectory()
		//		+ FilePath, FileName);
		//	FileInputStream fis = new FileInputStream(file);
		String content = info.getContent();
		ByteArrayInputStream strIs = new  ByteArrayInputStream(content.getBytes());
		try {
			Document document = builder.build(strIs);
			Element root = document.getRootElement();// ��ø��ڵ�<bookstore>
			if (root == null)
			{
				return;
			}
			// Namespace ns = root.getNamespace();
			// schemaLocation = root.g.getAttributeValue(Name_SchemaLocation, ns);
			// schemaLocation = root.getAttributeValue(Name_SchemaLocation);
			// xsi = root.getAttributeValue(Name_Xsi);
			// xmlns = root.getAttributeValue(Name_Xmlns);

			List<Element> list = root.getChildren();// ��ø��ڵ���ӽڵ�
			for (Element elem : list)
			{
				String name = elem.getName();
				Log.debug(this.getClass(), "name = " + name);
				if (name == null || name.length() <= 0)
				{
					return;
				}
				if (name.equals(Name_Sub))
				{
					parseSub(elem);
				}
			}
		}catch (Exception e)
		{
			e.printStackTrace();
		}

	}

	public void parseSub(Element elem) throws JDOMException
	{
		if (elem == null)
		{
			return;
		}
		uri = elem.getAttributeValue(Name_Uri);
		ruleMap = new HashMap<String, String>();
		List<Element> list = elem.getChildren();// ��ø��ڵ���ӽڵ�
		for (Element subElem : list)
		{
			String name = subElem.getName();
			Log.debug(this.getClass(), "name = " + name);
			if (name == null || name.length() <= 0)
			{
				return;
			}
			if (name.equals(DisplayName.Name))
			{
				displayName = new DisplayName();
				displayName.parse(subElem);
			} else if (name.equals(ListEntry.Name))
			{
				listEntry = new ListEntry();
				listEntry.parse(subElem);
			} else if (name.equals(PreferredVoiceEncodings.Name))
			{
				preferredVoiceEncodings = new PreferredVoiceEncodings();
				preferredVoiceEncodings.parse(subElem);
			} else if (name.equals(Ruleset.Name))
			{
				ruleset = new Ruleset();
				ruleset.parse(subElem);
			} else if (name.equals(SupportedServices.Name))
			{
				supportedServices = new SupportedServices();
				supportedServices.parse(subElem);
			} else
			{
				String value = subElem.getText();
				Log.debug(this.getClass(), "name = " + name + " value = "
						+ value);
				if (name != null && name.length() > 0 && value != null
						&& value.length() > 0)
				{
					ruleMap.put(name, value);
				}
			}
		}
	}

	public String toString()
	{
		StringBuffer strBuf = new StringBuffer("\r\n");
		strBuf.append("<").append(Name).append(">").append("\r\n");
		strBuf.append("    ").append("<").append(Name_Sub).append(" ")
		.append(Name_Uri).append("=\"").append(uri).append("\">");

		strBuf.append(displayName);
		strBuf.append(listEntry);
		strBuf.append(preferredVoiceEncodings);
		for (Iterator<String> itor = ruleMap.keySet().iterator(); itor
				.hasNext();)
		{
			String name = itor.next();
			String value = ruleMap.get(name);
			strBuf.append("        ").append("<").append(Namespace_Mcpttgi)
			.append(":").append(name).append(">");
			strBuf.append(value);
			strBuf.append("</").append(Namespace_Mcpttgi).append(":")
			.append(name).append(">").append("\r\n");
		}
		strBuf.append(ruleset);
		strBuf.append(supportedServices);

		strBuf.append("    ").append("</").append(Name_Sub).append(">")
		.append("\r\n");
		strBuf.append("</").append(Name).append(">");

		return strBuf.toString();
	}


	Handler handler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch(msg.what)
			{
			case OP_SUC:
				String fileName = msg.obj.toString();
				if(callback != null)
				{
					callback.parserFileSuc(fileName);
				}
				break;
			case OP_FAILED:
				String errStr = msg.obj.toString();
				if(callback != null)
				{
					callback.parserFileFailed(groupName,errStr);
				}
				break;
			}
		}
	};
	@Override  
	public void runReadFromSvrThread(final XcapDoc doc,final String rootPath,final String accessToken,IParserCallback parserCallback)
	{
		this.callback = parserCallback;
		Runnable runnable = new Runnable(){
			@Override
			public void run() {
				// TODO: http request.
				try
				{
					readFromSvr(doc,rootPath,accessToken);
				} catch (Exception ex)
				{
					// TODO Auto-generated catch block
					ex.printStackTrace();
					//   		    Exception e =  new HttpFailedException("run",ex.toString());
					//   		    sendOpResultMsg(OP_FAILED,e);
					String fileName = doc.getFileName();
					sendOpResultMsg(OP_FAILED,"readFromSvr fileName = " + fileName + " Exception = " + ex);
				}
			}
		};
		new Thread(runnable).start();
	}

	private void readFromSvr(XcapDoc doc, String rootPath, String accessToken) throws Exception
	{
		// TODO Auto-generated method stub
		Log.debug(getClass(), "readFromSvr doc = " + doc + " rootPath = " + rootPath );
		String subPath = doc.getSel();
		String path = rootPath + "/"+subPath;
		Log.debug(getClass(), "path = " + path);
		HttpOperator operator = new HttpOperator();
		//	try
		//	{
		Response response = null;//operator.httpGetRequestByAccessToken(path, accessToken);
		
		if(accessToken != null)
		{
			response = operator.httpGetRequestByAccessToken(path, accessToken);
		}
		else
		{
			response = operator.httpGetRequest(path);
		}
		int code = response.code();
		Log.debug(getClass(), "readFromSvr code = " + code);
		if(code == 200)
		{
			InputStream instreams = response.body().byteStream();
			String content = CommonFunc.convertStreamToString(instreams);
			Log.debug(getClass(), "Content = " + content);

			String groupName = doc.getGroupName();
			String eTag = doc.getNewEtag();
			info = new ConfigFileInfo(groupName,eTag,content);
			parse(info);
			syncToDb(info);
			saveInfoToDb();

			sendOpResultMsg(OP_SUC,groupName);
		}
		else
		{
			sendOpResultMsg(OP_FAILED,"readFromSvr code = " + code);
			//		notifyFailed(parserCallback,"readFromSvr code = " + code);
		}

		//	} catch (Exception e)
		//	{
		//	    // TODO: handle exception
		//	    e.printStackTrace();
		//	    notifyFailed(parserCallback,"readFromSvr Exception = " + e);
		//	}
	}


	private void sendOpResultMsg(int what,Object obj)
	{
		Message msg = handler.obtainMessage(what, obj);
		msg.sendToTarget();
	}

	private void notifyFailed(IParserCallback parserCallback,String fileName,String errStr)
	{
		if(parserCallback != null)
		{
			parserCallback.parserFileFailed(fileName,errStr);
		}
	}

	private void saveGroupMemberInfoList()
	{
		if(this.dbOperator == null)
		{
			return;
		}
		String groupAddrId = AddrInfo.toNumFromSipUrl(uri);
		Log.debug(getClass(), "saveGroupMemberInfoList groupAddrId = " + groupAddrId + " listEntry = " + listEntry);
		if(listEntry != null
				&& listEntry.getEntryList() != null)
		{
			this.dbOperator.delAllMembInfo(groupAddrId);
			List<Entry> list = listEntry.getEntryList();
			Log.debug(getClass(), "saveGroupMemberInfoList list = " + list);
			if(list != null
					&& list.size() > 0)
			{
				for(Iterator<Entry> iter = list.iterator();iter.hasNext();)
				{
					Entry callUri = iter.next();
					String urlEntry = callUri.getUri();
					String addId = AddrInfo.toNumFromSipUrl(urlEntry);
					String name = callUri.getDisplayName();
					String value = callUri.getUserPriority();
					int priority = CheckData.parseInt(value);

					GroupMembInfo info = new GroupMembInfo(groupAddrId,addId,name,urlEntry,priority);
					Log.debug(getClass(), "saveGroupMemberInfoList info = " + info);
					this.dbOperator.addMembInfo(info);
				}
			}
		}
	}

	@Override
	public void syncToSvr()
	{
		// TODO Auto-generated method stub
		Log.debug(getClass(), "syncToSvr");

	}

	@Override
	public ConfigFileInfo readFromDb(String groupName)
	{
		// TODO Auto-generated method stub
		Log.debug(getClass(), "readFromDb groupName = " + groupName);
		info = dbOperator.getGroupConfigFileInfoByGroupName(groupName);
		Log.debug(getClass(), "readFromDb info = " + info);
		return info;
	}

	@Override
	public void syncToDb(ConfigFileInfo info)
	{
		// TODO Auto-generated method stub
		Log.debug(getClass(), "syncToDb info = " + info);
		dbOperator.addGroupConfigFileInfo(info);
	}

	@Override
	public void saveInfoToDb()
	{
		// TODO Auto-generated method stub
		Log.debug(getClass(), "saveInfoToDb");
		saveGroupMemberInfoList();
	}
}
